using System.Collections;
using Slaks.Graphs.Wordnet;

namespace Slaks.Graphs.Algorithms.Wordnet
{
	public class SynonymMaxCommonSubGraphVertexEdgeCount
	{
		public static int SynonymLevelWithinSense = 2;
		public static int SynonymLevelBetweenSense = 2;

		public static Graph GetMCS(Graph one, Graph two)
		{
			WordnetGraph graphOne = (WordnetGraph) one;
			WordnetGraph graphTwo = (WordnetGraph) two;

			WordnetGraph bigGraph;
			WordnetGraph smallGraph;
			if (graphOne.GetVertexCount() > graphTwo.GetVertexCount())
			{
				bigGraph = graphOne;
				smallGraph = graphTwo;
			}
			else
			{
				bigGraph = graphTwo;
				smallGraph = graphOne;
			}

			//one.SortVertices();
			//two.SortVertices());

			WordnetGraph commonGraph = new WordnetGraph();

			WordnetVertex commonVertex;
			WordnetVertex commonVertexNext;

			#region find vertices

			long vertexId;
			bool isSynFound = false;
			int synonymLevelWithinSense = 0;
			int synonymLevelBetweenSense = 0;
			WordnetVertex tempVertex;
			foreach (WordnetVertex vertex in bigGraph.GetVertexList())
			{
				vertexId = vertex.GetId();
				tempVertex = smallGraph.GetVertexWithSynonymLookUp(vertexId, SynonymLevelBetweenSense, SynonymLevelWithinSense);
				if (tempVertex != null)
				{
					//create node id in common graph which equals to the id of the second graph in which synonym of the
					//vertexId was found
					commonVertex = commonGraph.CreateAddVertex(tempVertex.GetId());
					if (tempVertex.GetId() != vertexId && commonVertex.IsDirty == false)
					{
						commonVertex.IsDirty = true;
						//assign vertexId as direct synonym id of the tempVertex
						commonVertex.DirectSynonymId = vertexId;
					}
				}
			} //end of foreach

			#endregion

			#region find edges

			VertexList commonVertexList = commonGraph.GetVertexList();
			if (commonVertexList.Count <= 1) return commonGraph;

			Vertex vertexBigGraph;
			Vertex vertexSmallGraph;

			Vertex vertexBigGraphNext;
			Vertex vertexSmallGraphNext;

			long commonVertexIdBigGraph = 0;
			long commonVertexIdSmallGraph = 0;

			long nextIdBigGraph;
			long nextIdSmallGraph;
			long commonIdNext;
			IDictionary sectionsOne, sectionsTwo;

			for (int i = 0; i < commonVertexList.Count; i++)
			{
				commonVertex = (WordnetVertex) commonVertexList[i];
				if (commonVertex.IsDirty)
				{
					commonVertexIdBigGraph = commonVertex.DirectSynonymId;
				}
				else commonVertexIdBigGraph = commonVertex.GetId();
				commonVertexIdSmallGraph = commonVertex.GetId();

				vertexBigGraph = bigGraph.GetVertex(commonVertexIdBigGraph);
				vertexSmallGraph = smallGraph.GetVertex(commonVertexIdSmallGraph);

				for (int j = i; j < commonVertexList.Count; j++)
				{
					commonVertexNext = (WordnetVertex) commonVertexList[j];
					if (commonVertexNext.IsDirty)
					{
						nextIdBigGraph = commonVertexNext.DirectSynonymId;
					}
					else nextIdBigGraph = commonVertexNext.GetId();

					nextIdSmallGraph = commonVertexNext.GetId();

					sectionsOne = vertexBigGraph.GetSectionsIfConnected(nextIdBigGraph);
					sectionsTwo = vertexSmallGraph.GetSectionsIfConnected(nextIdSmallGraph);

					ICollection sectionsOneKeys = sectionsOne.Keys;

					foreach (string section in sectionsOneKeys)
					{
						if (sectionsTwo.Contains(section))
						{
							commonVertexList[i].AddEdge(commonVertexList[j], section);
						}
					}

					if (commonVertexIdBigGraph == nextIdBigGraph) continue;

					//find opposite directions
					vertexBigGraphNext = bigGraph.GetVertex(nextIdBigGraph);
					vertexSmallGraphNext = smallGraph.GetVertex(nextIdSmallGraph);

					sectionsOne = vertexBigGraphNext.GetSectionsIfConnected(commonVertexIdBigGraph);
					sectionsTwo = vertexSmallGraphNext.GetSectionsIfConnected(commonVertexIdSmallGraph);

					sectionsOneKeys = sectionsOne.Keys;
					foreach (string section in sectionsOneKeys)
					{
						if (sectionsTwo.Contains(section))
						{
							commonVertexList[j].AddEdge(commonVertexList[i], section);
						}
					}

				} //end of for
			}

			#endregion

			return commonGraph;
		}
	}
}